package org.dromara.pay.controller;

import cn.binarywang.wx.miniapp.util.WxMaConfigHolder;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.dromara.business.domain.Audit;
import org.dromara.business.service.AuditService;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.ProfilesUtils;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.pay.config.WxPayConfig;
import org.dromara.pay.domain.TopUp;
import org.dromara.pay.domain.request.PayParam;
import org.dromara.pay.service.TopUpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 支付接口
 *
 * @author zlj
 * @since 2023/7/31
 */
@Validated
@RequiredArgsConstructor
@RestController
@Slf4j
@RequestMapping("/pay")
public class PayController {
    @Autowired
    private WxPayConfig wxPayConfig;
    private final TopUpService topUpService;
    private final AuditService auditService;

    /**
     * 充值接口
     *
     * @return 唤起充值参数
     */
    @SaIgnore
    @RepeatSubmit(interval = 2, timeUnit = TimeUnit.SECONDS, message = "请勿重复操作")
    @PostMapping("/topUp")
    public R<JSONObject> topUp(@Validated @RequestBody PayParam payParam) {
        return R.ok(topUpService.topUp(payParam));
    }

    /**
     * 查询订单是否支付成功
     *
     * @param topUpId 订单id
     * @return true: 支付成功  false: 支付失败
     */
    @GetMapping("/getUserIsPay")
    public R<Boolean> getUserIsPay(@RequestParam Long topUpId) {
        return R.ok(topUpService.getUserIsPay(topUpId));
    }

    /**
     * 退款
     *
     * @param topUpId 订单流水id
     * @return true:成功 false:失败
     */
    @RepeatSubmit(interval = 2, timeUnit = TimeUnit.SECONDS, message = "请勿重复操作")
    @PostMapping("/refund")
    public R<Boolean> refund(@RequestParam Long topUpId) {
        return R.ok(topUpService.refund(topUpId));
    }


    /**
     * 小程序获取二维码
     *
     * @param scene 携带的参数
     * @param page  扫码进入的页面地址 例如： pages/home/index
     * @return 二维码 （前端 <img :src="返回结果"/> 就可以）
     */
    @SaIgnore
    @GetMapping(value = "/xcxGetQrCode")
    public String xcxGetQrCode(String scene, @RequestParam String page) {
        try {
            // envVersion: develop #要打开的小程序版本。正式版为 "release"，体验版为 "trial"，开发版为 "develop"。默认是正式版。
            byte[] qrCodeBytes = wxPayConfig.wxMaService().getQrcodeService()
                .createWxaCodeUnlimitBytes(
                    scene,
                    page,
                    false,
                    ProfilesUtils.check() ? "release" : "develop",
                    430,
                    true,
                    null,
                    false);
            return "data:image/jpeg;base64," + new String(Base64.getEncoder().encode(qrCodeBytes));
        } catch (WxErrorException e) {
            log.error(e.getMessage(), e);
            return e.toString();
        } finally {
            //清理ThreadLocal
            WxMaConfigHolder.remove();
        }
    }

    @GetMapping("/getCwTj")
    public R<Map<String, Object>> getCwTj() {
        BigDecimal ySumMoney = new BigDecimal(0);
        BigDecimal nSumMoney = new BigDecimal(0);
        BigDecimal ySumMoneyDisburse = new BigDecimal(0);
        BigDecimal nSumMoneyDisburse = new BigDecimal(0);

        Map<String, Object> map = new HashMap<>();
        LambdaQueryWrapper<TopUp> lambdaQueryWrapper = new LambdaQueryWrapper<TopUp>();
        lambdaQueryWrapper.eq(TopUp::getStatus,"2");
        String initiateTime = DateUtil.beginOfMonth(new Date()).toString();
        String endTime = DateUtil.endOfMonth(new Date()).toString();
        lambdaQueryWrapper.between(TopUp::getCreateTime, initiateTime,endTime);

        List<TopUp> listY = topUpService.list(lambdaQueryWrapper);
        for (TopUp t:listY){
            ySumMoney = ySumMoney.add(t.getTotal());
        }

        LambdaQueryWrapper<TopUp> lambdaQueryWrapper2 = new LambdaQueryWrapper<TopUp>();
        lambdaQueryWrapper2.eq(TopUp::getStatus,"2");
        String initiateTime2 = DateUtil.beginOfYear(new Date()).toString();
        String endTime2 = DateUtil.endOfYear(new Date()).toString();
        lambdaQueryWrapper.between(TopUp::getCreateTime, initiateTime2,endTime2);

        List<TopUp> listN = topUpService.list(lambdaQueryWrapper2);
        for (TopUp t:listN){
            nSumMoney = nSumMoney.add(t.getTotal());
        }


        LambdaQueryWrapper<Audit> lambdaQueryWrapper3 = new LambdaQueryWrapper<Audit>();
        lambdaQueryWrapper3.eq(Audit::getStatus,"1");
        String initiateTime3 = DateUtil.beginOfMonth(new Date()).toString();
        String endTime3 = DateUtil.endOfMonth(new Date()).toString();
        lambdaQueryWrapper3.between(Audit::getCreateTime, initiateTime3,endTime3);
        List<Audit> listYByAudit = auditService.list(lambdaQueryWrapper3);
        for (Audit a:listYByAudit){
            ySumMoneyDisburse = ySumMoneyDisburse.add(a.getBalance());
        }

        LambdaQueryWrapper<Audit> lambdaQueryWrapper4 = new LambdaQueryWrapper<Audit>();
        lambdaQueryWrapper4.eq(Audit::getStatus,"1");
        String initiateTime4 = DateUtil.beginOfMonth(new Date()).toString();
        String endTime4 = DateUtil.endOfMonth(new Date()).toString();
        lambdaQueryWrapper3.between(Audit::getCreateTime, initiateTime4,endTime4);
        List<Audit> listNByAudit = auditService.list(lambdaQueryWrapper4);
        for (Audit a:listNByAudit){
            nSumMoneyDisburse = nSumMoneyDisburse.add(a.getBalance());
        }

        map.put("ySumMoney",ySumMoney);
        map.put("nSumMoney",nSumMoney);
        map.put("ySumMoneyDisburse",ySumMoneyDisburse);
        map.put("nSumMoneyDisburse",nSumMoneyDisburse);
        return R.ok(map);
    }
}
